/*
 * ============================================================================
 *
 *       Filename:  main.c
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  08/02/2018 10:08:32 AM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  xiaojian jiang (Adams), linfeng2010jxj@163.com
 *   Organization:  
 *
 * ============================================================================
 */

#include <stdio.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include "cJSON.h"

#define DEV_NAME "/dev/ttyUSB2"
#define BUFSIZE (1024)


typedef struct cell_information_response
{
	int cell_mod; /* 0-GSM, 1-TDS, 2-WCDMA, 3-LTE */
	int mmc;/* 移动国家号码460-中国 */
	int mnc;/* 移动网络号码：00-移动,01-联通,11-电信 */
	char tac[10]; /* 位置区更新 LTE下为TAC */
	char cellid[10]; /* 小区ID */
	int arfcn; /* 主频 */
	int pci; /* 物理小区ID */
	int rxlevel; /* 信号强度 */
} cell_info_t;


int read_flag = 0;

void read_model_response(FILE *file);
//void *read_model_response(void *arg);

/* 创建线程 */
void safe_pthread_create(void *(*start_routine) (void *), void *arg)
{
	pthread_attr_t attr; 
	pthread_t mythread;

	if(pthread_attr_init(&attr)) {
		printf("pthread_attr_init faild: %s(%d)\n",
			strerror(errno), errno);
		exit(-1);
	}
	if(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) {
		printf("pthread_setdetach faild: %s(%d)\n",
			strerror(errno), errno);
		exit(-1);
	}
	if(pthread_create(&mythread, &attr, start_routine, arg)) {
		printf("pthread_create faild: %s(%d)\n",
			strerror(errno), errno);
		exit(-1);
	}
}

int set_opt(int fd,int nSpeed,int nBits,char nEvent,int nStop)
{
	struct termios newttys1,oldttys1;

	if(tcgetattr(fd,&oldttys1)!=0)     /*保存原先串口配置*/
	{
		perror("Setupserial 1");
		return -1;
	}

	bzero(&newttys1,sizeof(newttys1));       /*将一段内存区域的内容全清为零*/
	newttys1.c_cflag|=(CLOCAL|CREAD );       /*CREAD 开启串行数据接收，CLOCAL并打开本地连接模式*/   

	newttys1.c_cflag &=~CSIZE;              /*设置数据位数*/
	switch(nBits)     /*选择数据位*/  
	{
	case 7:
		newttys1.c_cflag |=CS7;
		break;
	case 8:
		newttys1.c_cflag |=CS8;
		break;
	}
	switch( nEvent )    /*设置校验位 */ 
	{
	case '0':       /*奇校验  */
		newttys1.c_cflag |= PARENB;             /*开启奇偶校验 */ 
		newttys1.c_iflag |= (INPCK | ISTRIP);   /*INPCK打开输入奇偶校验；ISTRIP去除字符的第八个比特*/  
		newttys1.c_cflag |= PARODD;             /*启用奇校验(默认为偶校验)*/  
		break;
	case 'E' :       /*偶校验  */
		newttys1.c_cflag |= PARENB;             /*开启奇偶校验 */ 
		newttys1.c_iflag |= ( INPCK | ISTRIP);  /*打开输入奇偶校验并去除字符第八个比特  */
		newttys1.c_cflag &= ~PARODD;            /*启用偶校验；  */
		break;
	case 'N':     /*关闭奇偶校验*/
		newttys1.c_cflag &= ~PARENB;
		break;
	}

	switch( nSpeed )        /*设置波特率 */ 
	{
	case 2400:
		cfsetispeed(&newttys1, B2400);    /*设置输入速度*/
		cfsetospeed(&newttys1, B2400);    /*设置输出速度*/
		break;
	case 4800:
		cfsetispeed(&newttys1, B4800);
		cfsetospeed(&newttys1, B4800);
		break;
	case 9600:
		cfsetispeed(&newttys1, B9600);
		cfsetospeed(&newttys1, B9600);
		break;
	case 115200:
		cfsetispeed(&newttys1, B115200);
		cfsetospeed(&newttys1, B115200);
		break;
	default:
		cfsetispeed(&newttys1, B9600);
		cfsetospeed(&newttys1, B9600);
		break;
	}

	if( nStop == 1)   /*设置停止位；若停止位为1，则清除CSTOPB，若停止位为2，则激活CSTOPB*/ 
	{
		newttys1.c_cflag &= ~CSTOPB;      /*默认为送一位停止位； */ 
	}
	else if( nStop == 2)
	{
		newttys1.c_cflag |= CSTOPB;       /*CSTOPB表示送两位停止位；*/  
	}

	/*设置最少字符和等待时间，对于接收字符和等待时间没有特别的要求时*/
	newttys1.c_cc[VTIME] = 0; /*非规范模式读取时的超时时间； */ 
	newttys1.c_cc[VMIN]  = 0;  /*非规范模式读取时的最小字符数；*/  

	tcflush(fd ,TCIFLUSH); /*tcflush清空终端未完成的输入/输出请求及数据；TCIFLUSH表示清空正收到的数据，且不读取出来 */
	/* 在完成配置后，需要激活配置使其生效*/
	if((tcsetattr( fd, TCSANOW,&newttys1))!=0) /*TCSANOW不等数据传输完毕就立即改变属性*/  
	{
		perror("com set error");
		return -1;
	}
	return 0;
}


#define CHINA_MOBILE (0)
#define CHINA_UNICOM (1)
#define CHINA_NET (2)

#define UNLOCK_PLMN  (0)
#define LOCK_PLMN  (1)

#define GSM_MODE (0)
#define LTE_MODE  (3)

int main (int argc, char *argv[])
{
	int fd;
	char read_buf[BUFSIZE];
	fd = open( DEV_NAME, O_RDWR|O_NOCTTY|O_NDELAY); /* ttyUSB2为SIM7100的AT指令口*/
	if (fd == -1) {
		perror("open model "DEV_NAME"error!");
		return -1;
	}
	FILE *file = fdopen(fd, "w+");
	if (file == NULL) {
		perror("fdopen error!");
		close(fd);
		return -1;
	}
	set_opt( fd,115200,8,'N',1);
	char act_cmd[64] = {0};
	int len = 0;
	char *plmn = "46000";
	while (1) {
		/* check LTE model */
		len = snprintf(act_cmd, 64, "AT^MODECONFIG=38\r\n");
		printf("<<<----CMD:%s\n", act_cmd);
		write(fd, act_cmd, len);
		usleep(500000);
		/* lock plmn */
		len = snprintf(act_cmd, 64, "AT+LOCKPLMN=%d,\"%s\",%d\r\n", LOCK_PLMN, plmn, LTE_MODE);
		printf("<<<----CMD:%s\n", act_cmd);
		write(fd, act_cmd, len);
		sleep(15);
		/* get cell information */
		len = snprintf(act_cmd, 64, "AT+SCELLINFO\r\n");
		printf("<<<----CMD:%s\n", act_cmd);
		write(fd, act_cmd, len);
		sleep(1);
		/* get all neighbor cell info */
		len = snprintf(act_cmd, 64, "AT+ANCELLINFO\r\n");
		printf("<<<----CMD:%s\n", act_cmd);
		write(fd, act_cmd, len);
		read_flag = 1;
		sleep(2);
		read_model_response(file);
	//	memset(read_buf, 0, BUFSIZE);
	//	read(fd, read_buf, BUFSIZE);
	//	printf(">>>----RES:%s\n",read_buf);
		sleep(10);
	}
	return 1;

}
#if 1
static int readline(FILE *file, char *buf, int bufsize)
{
	int nread;
	memset(buf, 0, bufsize);
	nread = fscanf(file, "%[^\r]", buf);
	if(nread  == EOF) {
		fprintf(stderr, "fscanf failed\n");
		return -1;
	}
	/* skip \r\n */
	char skip[2];
	fscanf(file, "%[\r\n]", &skip[0]);
	return 0;
}

void read_model_response(FILE *file)
{
	cJSON *object = cJSON_CreateObject();
	if (!object) return;
	cJSON *array = cJSON_CreateArray();
	if (!array) {
		cJSON_Delete(object);
		return;
	}
	cJSON_AddItemToObject(object, "ncells", array);
	printf("read model response...\n");
	char buf[BUFSIZE];
	int ret = 0;
	while (1) {
		ret = readline(file, buf, BUFSIZE);
		if (ret == -1) {
			read_flag = 0;
			break;
		}
		if (strstr(buf, "AT+") || strstr(buf, "OK")) {
			printf(">>>>-------REC:%s\n", buf);

		} else {
			printf("ststus:%s\n", buf);
			if (strstr(buf, "+SCELLINFO:")) {
				cell_info_t cell_info;
				sscanf(buf,
					"%*s%d,%d,%d,\"%04s\",\"%08s\",%d,%d,%d",
					&cell_info.cell_mod,
					&cell_info.mmc,
					&cell_info.mnc,
					cell_info.tac,
					cell_info.cellid,
					&cell_info.arfcn,
					&cell_info.pci,
					&cell_info.rxlevel);
				cJSON_AddNumberToObject(object, "cell_mod", cell_info.cell_mod);
				cJSON_AddNumberToObject(object, "mmc", cell_info.mmc);
				cJSON_AddNumberToObject(object, "mnc", cell_info.mnc);
				cJSON_AddStringToObject(object, "tac", cell_info.tac);
				cJSON_AddStringToObject(object, "cellid", cell_info.cellid);
				cJSON_AddNumberToObject(object, "arfcn", cell_info.arfcn);
				cJSON_AddNumberToObject(object, "pci", cell_info.pci);
				cJSON_AddNumberToObject(object, "rxlevel", cell_info.rxlevel);
			} else if (strstr(buf, "+ANCELLINFO:")){
				cell_info_t cell_info;
				int tmp = 0;
				sscanf(buf,
					"%*s%d,%d,%d,%d,%d,\"%4s\",\"%8s\",%d,%d,%d",
					&tmp, &tmp, &cell_info.cell_mod,
					&cell_info.mmc, &cell_info.mnc,
					cell_info.tac, cell_info.cellid,
					&cell_info.arfcn, &cell_info.pci,
					&cell_info.rxlevel);
				cJSON *obj = cJSON_CreateObject();
				if (obj) {
					cJSON_AddNumberToObject(obj,"cell_mod", cell_info.cell_mod);
					cJSON_AddNumberToObject(obj,"mmc", cell_info.mmc);
					cJSON_AddNumberToObject(obj,"mnc", cell_info.mnc);
					cJSON_AddStringToObject(obj,"tac", cell_info.tac);
					cJSON_AddStringToObject(obj,"cellid", cell_info.cellid);
					cJSON_AddNumberToObject(obj,"arfcn", cell_info.arfcn);
					cJSON_AddNumberToObject(obj,"pci", cell_info.pci);
					cJSON_AddNumberToObject(obj,"rxlevel", cell_info.rxlevel);
				}
				cJSON_AddItemToArray(array, obj);
			}
		}

	} /* end while */
	char *json_string = cJSON_Print(object);
	cJSON_Delete(object);
	if (json_string) {
		printf("json_string:%s\n", json_string);

	}
}
#endif
